package com.hzy.pay.alipay.service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.google.common.collect.Maps;
import com.hzy.pay.alipay.bean.*;
import com.hzy.pay.alipay.util.AlipayClientUtil;
import com.hzy.pay.alipay.util.AlipayConfigUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

/**
 * 阿里支付服务
 * 
 * @author zhuowei.luo
 * @date 2018/7/9
 */
public class AlipayApiServiceImpl implements AlipayApiService {

	private static final Logger logger = LoggerFactory.getLogger(AlipayApiServiceImpl.class);
	private AlipayClient client = AlipayClientUtil.getDefaultAlipayClient();

    @Override
    public void AlipayNotify(HttpServletRequest request) throws Exception {
        //获取支付宝POST过来反馈信息
        Map<String,String> params = Maps.newConcurrentMap();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfigUtil.publicKeyForAlipay, AlipayConfigUtil.charset, AlipayConfigUtil.signType); //调用SDK验证签名

        //——请在这里编写您的程序（以下代码仅作参考）——

	/* 实际验证过程建议商户务必添加以下校验：
	1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
	2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
	3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
	4、验证app_id是否为该商户本身。
	*/
        if(signVerified) {//验证成功
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            if(trade_status.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //付款完成后，支付宝系统发送该交易状态通知
            }

            System.out.println("success");

        }else {//验证失败
            System.out.println("fail");

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }

        //——请在这里编写您的程序（以上代码仅作参考）——
    }

    @Override
    public AlipayTradePagePayResponse pagePay(PagePayRequest request, String notifyUrl) throws AlipayApiException {
        String json = null;
        try {
            json = request.toJson();
            AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
            req.setNotifyUrl(notifyUrl);
            req.setBizContent(json);
            AlipayTradePagePayResponse resp = client.execute(req);
            if (resp != null && resp.isSuccess()) {
                logger.info("alipay.pagePay，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
            } else {
                logger.error("alipay.pagePay，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
            }
            return resp;
        } catch (AlipayApiException e) {
            logger.error("alipay.pagePay，请求异常！req={}", json, e);
            throw e;
        }
    }

    @Override
	public AlipayTradePrecreateResponse precreate(PrecreateRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradePrecreateRequest req = new AlipayTradePrecreateRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradePrecreateResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.precreate，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.precreate，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.precreate，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeCreateResponse create(CreateRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeCreateRequest req = new AlipayTradeCreateRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradeCreateResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.create，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.create，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.create，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradePayResponse pay(PayRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradePayRequest req = new AlipayTradePayRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradePayResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.pay，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.pay，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.pay，请求异常！req={}", json, e);
			throw e;
		}
	}
	
	@Override
	public String appClientPay(AppClientPayRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			if (request != null) {
				json = request.toJson();
			}
			AlipayTradeAppPayRequest req = new AlipayTradeAppPayRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradeAppPayResponse resp = client.pageExecute(req, "GET");
			String url = resp.getBody();
			return url.substring(url.indexOf("?") + 1);
		} catch (AlipayApiException e) {
			logger.error("alipay.appClientPay，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeAppPayResponse appPay(AppPayRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			if (request != null) {
				json = request.toJson();
			}
			AlipayTradeAppPayRequest req = new AlipayTradeAppPayRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradeAppPayResponse resp = client.pageExecute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.appPay，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.appPay，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.appPay，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeWapPayResponse wapPay(WapPayRequest request, String notifyUrl) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeWapPayRequest req = new AlipayTradeWapPayRequest();
			req.setNotifyUrl(notifyUrl);
			req.setBizContent(json);
			AlipayTradeWapPayResponse resp = client.pageExecute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.wapPay，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.wapPay，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.wapPay，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeCloseResponse close(CloseRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeCloseRequest req = new AlipayTradeCloseRequest();
			req.setBizContent(json);
			AlipayTradeCloseResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.close，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.close，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.close，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeCancelResponse cancel(CancelRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeCancelRequest req = new AlipayTradeCancelRequest();
			req.setBizContent(json);
			AlipayTradeCancelResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.cancel，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.cancel，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.cancel，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public RefundResponse refund(RefundRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeRefundRequest req = new AlipayTradeRefundRequest();
			req.setBizContent(json);
			AlipayTradeRefundResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.refund，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.refund，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			RefundResponse response = new RefundResponse();
			BeanUtils.copyProperties(resp, response);
			return response;
		} catch (AlipayApiException e) {
			logger.error("alipay.refund，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public AlipayTradeOrderSettleResponse settle(SettleRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeOrderSettleRequest req = new AlipayTradeOrderSettleRequest();
			req.setBizContent(json);
			AlipayTradeOrderSettleResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.settle，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.settle，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.settle，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public QueryResponse query(QueryRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeQueryRequest req = new AlipayTradeQueryRequest();
			req.setBizContent(json);
			AlipayTradeQueryResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.query，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.query，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			QueryResponse response = new QueryResponse();
			BeanUtils.copyProperties(resp, response);
			return response;
		} catch (AlipayApiException e) {
			logger.error("alipay.query，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public RefundQueryResponse refundQuery(RefundQueryRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipayTradeFastpayRefundQueryRequest req = new AlipayTradeFastpayRefundQueryRequest();
			req.setBizContent(json);
			AlipayTradeFastpayRefundQueryResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.refundQuery，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.refundQuery，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			RefundQueryResponse response = new RefundQueryResponse();
			BeanUtils.copyProperties(resp, response);
			return response;
		} catch (AlipayApiException e) {
			logger.error("alipay.refundQuery，请求异常！req={}", json, e);
			throw e;
		}
	}

	@Override
	public String getOauthUrl(String redirectUri, OauthScopeEnum scope) throws UnsupportedEncodingException {
		try {
			if (scope == null) {
				scope = OauthScopeEnum.AUTH_BASE;
			}
			StringBuilder sb = new StringBuilder();
			sb.append(AlipayConfigUtil.oauthUrl);
			sb.append("?app_id=").append(AlipayConfigUtil.appId);
			sb.append("&scope=").append(scope.getScope());
			sb.append("&redirect_uri=").append(URLEncoder.encode(redirectUri, AlipayConfigUtil.charset));
			logger.info("alipay.getOauthUrl，redirectUri={}，url={} ", redirectUri, sb.toString());
			return sb.toString();
		} catch (UnsupportedEncodingException e) {
			logger.error("alipay.getOauthUrl，redirectUri={}", redirectUri, e);
			throw e;
		}
	}
	
	@Override
	public AlipaySystemOauthTokenResponse oauthToken(OauthTokenRequest request) throws AlipayApiException {
		String json = null;
		try {
			json = request.toJson();
			AlipaySystemOauthTokenRequest req = new AlipaySystemOauthTokenRequest();
			req.setGrantType(request.getGrantType());
			req.setCode(request.getCode());
			req.setRefreshToken(request.getRefreshToken());
			AlipaySystemOauthTokenResponse resp = client.execute(req);
			if (resp != null && resp.isSuccess()) {
				logger.info("alipay.oauthToken，执行请求！req={}, resp={}", json, JSONObject.toJSONString(resp));
			} else {
				logger.error("alipay.oauthToken，请求失败！req={}, resp={}", json, JSONObject.toJSONString(resp));
			}
			return resp;
		} catch (AlipayApiException e) {
			logger.error("alipay.oauthToken，请求异常！req={}", json, e);
			throw e;
		}
	}
}
